package de.programmerspain.rv3sf.examples;

import java.awt.Color;
import java.util.concurrent.TimeUnit;

/**
 * A quick'n'dirty example showing some simple color animations. A new
 * frame is send every ~33ms to the Rainbowduino V3 controller(s) so that
 * the whole animation is running at ~30 frames per second.
 * 
 * Every specified command line argument will be handled as
 * a serial port name. Calling the class with:
 * 'java ColorChangerExample /dev/ttyUSB0'
 * will initialize one Rainbowduino controller whereas:
 * 'java ColorChangerExample /dev/ttyUSB0 /dev/ttyUSB1'
 * will initialize two Rainbowduino controllers and so forth.
 * 
 * @author Markus Lang (m@rkus-lang.de) | http://programmers-pain.de/ | https://code.google.com/p/rainbowduino-v3-streaming-firmware/
 */
public class ColorScrollExample extends AbstractExample {
	private boolean redReverse;
	private boolean greenReverse;
	private boolean blueReverse;
	
	/**
	 * @param args the command line arguments
	 */
	public ColorScrollExample(String args[]) {
		// construct rainbowduino instances
		super(args);
		
		// initialize variables
		this.redReverse = false;
		this.greenReverse = false;
		this.blueReverse = false;
		Color color = new Color(
				(int) (Math.random() * 255),
				(int) (Math.random() * 255),
				(int) (Math.random() * 255)
		);
		for (int pixel = 0; pixel < this.frame.length; pixel++) {
			this.frame[pixel] = color.getRGB();
		}
		
		// start internal executorService instances at 30 frames per seconds
		this.start(1000 / 30, TimeUnit.MILLISECONDS);
	}

	@Override
	protected void updateFrame() {
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				int pos = y * 8 + x;
				// split into red, green and blue colors
				int red = (int) ((this.frame[pos] >> 16) & 0xFF);
				int green = (int) ((this.frame[pos] >> 8) & 0xFF);
				int blue = (int) (this.frame[pos] & 0xFF);
				// increase or decrease color value
				if (this.redReverse) {
					red  = red - x;
				} else {
					red  = red + x;
				}
				if (this.blueReverse) {
					blue  = blue - x - 1;
				} else {
					blue = blue + x + 1;
				}
				if (this.greenReverse) {
					green  = green - x - 2;
				} else {
					green  = green + x + 2;
				}
				// limit max value
				if (red > 255) {
					red = 255;
					this.redReverse = true;
				}
				if (green > 255) {
					green = 255;
					this.greenReverse = true;
				}
				if (blue > 255) {
					blue = 255;
					this.blueReverse = true;
				}
				// limit min value
				if (red < 0) {
					red = 0;
					this.redReverse = false;
				}
				if (blue < 0) {
					blue = 0;
					this.blueReverse = false;
				}
				if (green < 0) {
					green = 0;
					this.greenReverse = false;
				}
				// store new color
				this.frame[pos] = (red << 16) | (green << 8) | (blue);
			}
		}
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new ColorScrollExample(args);
	}
}
